package com.honghu.cloud.service.impl;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.internal.org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.honghu.cloud.bean.Goods;
import com.honghu.cloud.bean.GoodsSpecProperty;
import com.honghu.cloud.bean.GoodsSpecification;
import com.honghu.cloud.bean.SeckillGoods;
import com.honghu.cloud.common.service.BaseService;
import com.honghu.cloud.dao.SeckillGoodsDao;
import com.honghu.cloud.dto.AccessoryDto;
import com.honghu.cloud.dto.OrderFormDto;
import com.honghu.cloud.feign.AccessoryFeignClient;
import com.honghu.cloud.feign.OrderFormFeignClient;
import com.honghu.cloud.redis.RedisUtil;
import com.honghu.cloud.service.IGoodsService;
import com.honghu.cloud.service.IGoodsSpecificationService;
import com.honghu.cloud.service.ISeckillGoodsService;
import com.honghu.cloud.utils.CommUtil;

/**
 * 秒杀商品表
 *
 * @author l
 * @email l@qq.com
 * @date 2021-04-15 11:28:53
 */
@Service
@Transactional(readOnly = true)
public class SeckillGoodsServiceImpl extends BaseService<SeckillGoods> implements ISeckillGoodsService {
	@Autowired
	private SeckillGoodsDao seckillGoodsDao;   
	@Autowired
	private RedisUtil redisUtil;  
	@Autowired
	private OrderFormFeignClient orderFormFeignClient;  
	@Autowired
	private IGoodsService goodsService;  
	@Autowired
	private AccessoryFeignClient accessoryFeignClient;
	@Autowired
	private IGoodsSpecificationService goodsSpecificationService;
    
    
	@Transactional(readOnly = false)
	public void batchDelObjs(List<SeckillGoods> objs) {
		if (objs != null && objs.size() > 0) {
			seckillGoodsDao.batchDelete(objs);
		}
	}


	public SeckillGoods getObjByProperty(String key, String operation_symbol, Object value) {
		Map<String, Object> maps = Maps.newHashMap();
		maps.put("operation_property", key);
		maps.put("operation_symbol", operation_symbol);
		maps.put("operation_value", value);
		List<SeckillGoods> objs = seckillGoodsDao.selectObjByProperty(maps);
		if (objs != null && objs.size() > 0) {
			return objs.get(0);
		}
		return null;
	}


	public List<SeckillGoods> selectObjByProperty(Map<String, Object> maps) {
		return seckillGoodsDao.selectObjByProperty(maps);
	}


	public List<SeckillGoods> queryPages(Map<String, Object> params) {
		return seckillGoodsDao.queryPages(params);
	}


	public List<SeckillGoods> queryPageListWithNoRelations(Map<String, Object> param) {
		return seckillGoodsDao.queryPageListWithNoRelations(param);
	}


	public List<SeckillGoods> queryPagesWithNoRelations(Map<String, Object> params, Integer currentPage, Integer pageSize) {
		return seckillGoodsDao.queryPagesWithNoRelations(params);
	}



	@Transactional(readOnly = false)
	public void batchDeleteByIds(List<Long> ids) {
		seckillGoodsDao.batchDeleteByIds(ids);
	}


	@Transactional(readOnly = false)
	public void saveEntity(SeckillGoods obj) {
		seckillGoodsDao.saveEntity(obj);
	}


	@Transactional(readOnly = false)
	public void updateById(SeckillGoods obj) {
		seckillGoodsDao.updateById(obj);
	}


	@Transactional(readOnly = false)
	public void deleteById(Long id) {
		seckillGoodsDao.deleteById(id);
	}


	public SeckillGoods selectByPrimaryKey(Long id) {
		return seckillGoodsDao.selectByPrimaryKey(id);
	}


	public List<SeckillGoods> queryPageList(Map<String, Object> params, Integer begin, Integer max) {
		return super.queryPageList(params, begin, max);
	}


	public List<SeckillGoods> queryPageList(Map<String, Object> params) {
		return this.queryPageList(params, null, null);
	}


	public int selectCount(Map<String, Object> params) {
		Integer c = seckillGoodsDao.selectCount(params);
		if (c == null) {
			return 0;
		}
		return c;
	}

	/**
	 * 秒杀开始, 将审核通过的秒杀商品表 的商品 放入redis 队列(商品有规格)
	 */
	@Override
	@Transactional(readOnly = false)
	public void secondKillBegins() {
		// 查询 秒杀商品表中, 待审核, 开始时间为当前的 商品 (有规格的要查询规格)
		List<SeckillGoods> timerList = seckillGoodsDao.timerList();
		for (SeckillGoods seckillGoods : timerList) {
			//Goods goods = goodsService.selectByPrimaryKey(seckillGoods.getGoods_id());
			Goods goods = (Goods) redisUtil.get("goods_"+seckillGoods.getGoods_id());
			if (goods == null)continue;
			goods.setSeckillGoods(seckillGoods);
			redisUtil.set("goods_"+goods.getId(), goods);
			// 该商品有规格,将规格放入队列
			if (goods.getInventory_type().equals("spec")) {
				String[] temp_ids = null;
				List<HashMap> list = JSON.parseArray(CommUtil.null2String(goods.getGoods_inventory_detail()),
						HashMap.class);
				for (Map temp : list) {
					String key = "seckill:" + goods.getId() + ";gsp:" + temp.get("id");
					temp_ids = CommUtil.null2String(temp.get("id")).split("_");
					Arrays.sort(temp_ids);
					int count = CommUtil.null2Int(temp.get("count"));
					if (count < 1)
						continue;
					for (Integer integer = 0; integer < count; integer++) {
						redisUtil.rightPush(key, goods.getId()+"");
					}
				}
			} else {// 该商品为全局规格,直接放入队列
				String key = "seckill:" + goods.getId() + ";" ;
				for (Integer integer = 0; integer < goods.getGoods_inventory(); integer++) {
					redisUtil.rightPush(key, goods.getId()+"");
				}
			}
			seckillGoods.setStatus(1);//秒杀活动开始
			
			redisUtil.set("seckillGoods_"+goods.getId(), seckillGoods,1000*60*60L);
			seckillGoodsDao.updateById(seckillGoods);
		}

	}


	@Override
	@Transactional(readOnly = false)
	public void secondKillEnd() {
		// 查询 秒杀商品表中, 待审核, 开始时间为当前的 商品 (有规格的要查询规格)
		List<SeckillGoods> timerList = seckillGoodsDao.timerListEnd();
		for (SeckillGoods seckillGoods : timerList) {
			Goods goods = goodsService.selectByPrimaryKey(seckillGoods.getGoods_id());
			// 该商品有规格,将规格放入队列
			if (goods.getInventory_type().equals("spec")) {
				String[] temp_ids = null;
				List<HashMap> list = JSON.parseArray(CommUtil.null2String(goods.getGoods_inventory_detail()),
						HashMap.class);
				for (Map temp : list) { 
					String key = "seckill:" + goods.getId() + ";gsp:" + temp.get("id");
					redisUtil.templateDelete(key);
				}
			} else {// 该商品为全局规格,直接放入队列
				String key = "seckill:" + goods.getId() + ";" ;
				redisUtil.templateDelete(key);
			}
			seckillGoods.setStatus(2);//秒杀活动结束
			seckillGoodsDao.updateById(seckillGoods);
			goods.setGoods_status(-1);
			goodsService.update(goods);
			redisUtil.remove("seckillGoods_"+goods.getId());
		}

	}

	/**
	 * 秒杀商品,成功 发送mq,创建订单  (0 抢购成功 1 秒杀活动已结算, 2 当前用户已经抢购过该商品，每人仅限抢购一件, 3商品已经被抢购完毕，请下次再来！)
	 */
	@Override
	public int secKill(Long currentUserId, String goods_id, String gsp) {
		// 返还给redis
		redisUtil.opsForSetmove("seckill:user:" + goods_id, currentUserId+"");
		
		Goods goods = (Goods) redisUtil.get("goods_" + goods_id);
		SeckillGoods seckillGoods = (SeckillGoods) redisUtil.get("seckillGoods_"+ goods_id);
		
		if (goods==null||seckillGoods==null||seckillGoods.getStatus() == -1) {
			return 1 ;
			//return ResponseCode.buildFailMap("秒杀活动已结束", null);
			// throw new SecKillException("秒杀活动已结束");
		}
		// 获取秒杀活动的商品ID
		String key = "seckill:" + goods_id + ";gsp:" + gsp;
		if(StringUtils.isEmpty(gsp)){
			 key = "seckill:" + goods_id+";";
		}
		//先移除元素
		 Object leftPop = redisUtil.leftPop(key);
		if (leftPop != null) {

			// 说明还有商品未被抢购
			String userKey = "seckill:user:" + goods.getId();
			// 判断当前用户是否已经抢购过
			boolean opsForSet = redisUtil.opsForSet(userKey, currentUserId + "");
			if (opsForSet) {
				// 将商品信息重新放回到抢购的队列中
				redisUtil.rightPush(key, goods.getId() + "");
				return 2 ;
			}
			// 将当前用户加入到抢购到商品的用户集合中
			redisUtil.opsForSetadd(userKey, currentUserId + "");
			//修改redis 商品信息数量
			goods.setGoods_inventory(goods.getGoods_inventory()-1);
			redisUtil.set("goods_" + goods_id, goods);
			return 0 ;
		} else {
			return 3 ;
			// throw new SecKillException("商品已经被抢购完毕，请下次再来！");
		}
	}


	@Override
	public void secondKillNoPay() { // order_cat为秒杀订单,未付款,过十分钟后
		List<OrderFormDto> secondKillNoPayOrder = orderFormFeignClient.getSecondKillNoPayOrder();
		for (OrderFormDto orderFormDto : secondKillNoPayOrder) {
			orderFormDto.setOrder_status(0); // 订单取消,
			List<Map> queryGoodsInfo = queryGoodsInfo(orderFormDto.getGoods_info());
			String gsp = "";
			String goods_id = "";
			for (Map map : queryGoodsInfo) {
				gsp = (String) map.get("goods_gsp_ids");
				goods_id = (String) map.get("goods_id");
			}
			// 先查看秒杀是否结束
			SeckillGoods seckillGoods = seckillGoodsDao.selectByGoodsId(goods_id);
			if (seckillGoods != null && seckillGoods.getStatus() == 1) {
				// 返还给redis
				String key = "seckill:" + goods_id + ";gsp:" + gsp;
				redisUtil.rightPush(key, goods_id);
				redisUtil.opsForSetmove("seckill:user:" + goods_id, orderFormDto.getUser_id());
			}
		}

	}
	/**
	 * 把商品json转换成map
	 * @param json
	 * @return
	 */
	public List<Map> queryGoodsInfo(String json) {
		List<Map> map_list = Lists.newArrayList();
		if ((json != null) && (!json.equals(""))) {
			map_list = JSON.parseArray(json, Map.class);
		}
		return map_list;
	}


	@Override
	public void secondKillBegins2() {
		List<SeckillGoods> timerList = seckillGoodsDao.timerSetRedis();
		for (SeckillGoods seckillGoods : timerList) {
			
			
			Goods goods = goodsService.selectByPrimaryKey(CommUtil.null2Long(seckillGoods.getGoods_id()));
			if (goods == null) {continue;}
			// 商品图片
			List<AccessoryDto> goods_photos = accessoryFeignClient.getGoodsPhotosByAccessoryId(goods.getId());
			goods_photos.add(0, goods.getGoods_main_photo());
			goods.setGoods_photos(goods_photos);

			// 查询商品规格集合
			List<GoodsSpecification> goods_specis = goodsSpecificationService.getGoodsIdSpecification(goods.getId());
			// 查询自定义规格
			if (StringUtils.isNotEmpty(goods.getGoods_specs_info()) && goods_specis.size() > 0) {
				List<Map> goods_specs_info = JSON.parseArray(goods.getGoods_specs_info(), Map.class);
				for (GoodsSpecification goods_speci : goods_specis) {
					for (Map map : goods_specs_info) {
						List<GoodsSpecProperty> properties = goods_speci.getProperties();
						for (GoodsSpecProperty goodsSpecProperty : properties) {
							if (map.get("id").equals(goodsSpecProperty.getId().toString())) {
								goodsSpecProperty.setValue(map.get("name").toString());
							}
						}
					}
				}
			}
			goods.setGoods_specis(goods_specis);
			redisUtil.set("goods_"+goods.getId(), goods);
		}
	}
}
